"""
WebSocket认证模块
"""
from fastapi import WebSocket, status
from config.env import WebSocketConfig, JwtConfig
import jwt
from loguru import logger


def verify_websocket_token(token: str) -> tuple[bool, str]:
    """
    验证WebSocket Token（同步函数，用于快速验证）
    
    Args:
        token: 认证Token
    
    Returns:
        (is_valid, user_id/error_message)
    """
    # 如果禁用认证，直接通过
    if not WebSocketConfig.ws_enable_auth:
        return True, "guest"
    
    if not token:
        return False, "缺少认证Token"
    
    try:
        # 方案1：验证JWT Token（推荐）
        if not WebSocketConfig.ws_auth_token:
            # 使用JWT认证
            payload = jwt.decode(
                token,
                JwtConfig.jwt_secret_key,
                algorithms=[JwtConfig.jwt_algorithm]
            )
            user_id = payload.get("user_id")
            if not user_id:
                return False, "Token无效：缺少user_id"
            
            return True, str(user_id)
        
        # 方案2：验证固定Token
        else:
            if token == WebSocketConfig.ws_auth_token:
                return True, "1"
            else:
                return False, "Token不匹配"
    
    except jwt.ExpiredSignatureError:
        # 临时方案：允许过期Token，但记录警告（为了解决前端重连问题）
        try:
            payload = jwt.decode(
                token,
                JwtConfig.jwt_secret_key,
                algorithms=[JwtConfig.jwt_algorithm],
                options={"verify_exp": False}
            )
            user_id = payload.get("user_id")
            if user_id:
                logger.warning(f"⚠️ 允许过期Token连接: user_id={user_id}")
                return True, str(user_id)
        except:
            pass
        return False, "Token已过期，请重新登录"
    
    except jwt.InvalidTokenError as e:
        return False, f"Token无效：{str(e)}"
    
    except Exception as e:
        logger.error(f"❌ Token验证异常：{e}")
        return False, "认证失败"


class WebSocketAuth:
    """WebSocket认证类"""
    
    @staticmethod
    async def verify_token(websocket: WebSocket, token: str = None) -> tuple[bool, str]:
        """
        验证Token
        
        Args:
            websocket: WebSocket连接
            token: 认证Token
        
        Returns:
            (is_valid, user_id/error_message)
        """
        # 如果禁用认证，直接通过
        if not WebSocketConfig.ws_enable_auth:
            logger.warning("⚠️  WebSocket认证已禁用（开发模式）")
            return True, "guest"
        
        if not token:
            return False, "缺少认证Token"
        
        try:
            # 方案1：验证JWT Token（推荐）
            if not WebSocketConfig.ws_auth_token:
                # 使用JWT认证
                payload = jwt.decode(
                    token,
                    JwtConfig.jwt_secret_key,
                    algorithms=[JwtConfig.jwt_algorithm]
                )
                user_id = payload.get("user_id")
                if not user_id:
                    return False, "Token无效：缺少user_id"
                
                logger.success(f"✅ JWT Token验证成功：用户 {user_id}")
                return True, str(user_id)
            
            # 方案2：验证固定Token
            else:
                if token == WebSocketConfig.ws_auth_token:
                    logger.success("✅ 固定Token验证成功")
                    return True, "1"
                else:
                    logger.warning(f"❌ Token不匹配：{token[:10]}...")
                    return False, "Token不匹配"
        
        except jwt.ExpiredSignatureError:
            # 临时方案：允许过期Token
            try:
                payload = jwt.decode(
                    token,
                    JwtConfig.jwt_secret_key,
                    algorithms=[JwtConfig.jwt_algorithm],
                    options={"verify_exp": False}
                )
                user_id = payload.get("user_id")
                if user_id:
                    logger.warning(f"⚠️ 允许过期Token连接: user_id={user_id}")
                    return True, str(user_id)
            except:
                pass
            logger.warning("❌ JWT Token已过期")
            return False, "Token已过期，请重新登录"
        
        except jwt.InvalidTokenError as e:
            logger.warning(f"❌ JWT Token无效：{str(e)}")
            return False, f"Token无效：{str(e)}"
        
        except Exception as e:
            logger.error(f"❌ Token验证异常：{e}")
            return False, "认证失败"
    
    @staticmethod
    async def authenticate(websocket: WebSocket) -> tuple[bool, str]:
        """
        WebSocket连接认证
        
        从URL参数或Header中获取Token并验证
        
        Args:
            websocket: WebSocket连接
        
        Returns:
            (is_valid, user_id/error_message)
        """
        # 方法1：从URL参数获取token（推荐）
        token = websocket.query_params.get("token")
        
        # 方法2：从Header获取token
        if not token:
            auth_header = websocket.headers.get("Authorization")
            if auth_header:
                if auth_header.startswith("Bearer "):
                    token = auth_header[7:]
                else:
                    token = auth_header
        
        # 验证Token
        return await WebSocketAuth.verify_token(websocket, token)
